<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
            "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>



<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="hevea 1.08">
<LINK rel="stylesheet" type="text/css" href="embroot.css">
<TITLE>
Asynchronous Communicating between Java and ECLiPSe
</TITLE>
</HEAD>
<BODY >
<A HREF="embroot046.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="embroot041.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
<A HREF="embroot048.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2 CLASS="section"><A NAME="htoc94">8.6</A>&nbsp;&nbsp;Asynchronous Communicating between Java and ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP><A NAME="@default246"></A></H2><UL>
<LI><A HREF="embroot047.html#toc51">Opening and closing asynchronous queues</A>
<LI><A HREF="embroot047.html#toc52">Opening an asychronous queue using ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> predicates</A>
<LI><A HREF="embroot047.html#toc53">Writing and reading ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> terms on queues</A>
</UL>
 
<A NAME="sec:ji-async-queue-streams"></A>
Starting with release 5.9, the <I>OutOfProcessEclipse</I>
and <I>RemoteEclipse</I> variants of the Java-ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> Interface also support
asynchronous queues through the class <I>AsyncEclipseQueue</I><A NAME="@default247"></A>.
These are essentially socket connections between ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> and Java, which
can be used independently of which side has control. <BR>
<BR>
An <I>AsyncEclipseQueue</I> queue is opened and closed in the same way as 
a <I>FromEclipseQueue</I> or <I>ToEclipseQueue</I>, but the following
differences exist:
<UL CLASS="itemize"><LI CLASS="li-itemize">
an asynchronous queue can be read/written from the Java side
even while the ECLiPSe side has control, e.g. during an RPC. This
obviously has to happen from a different thread than the one that
executes the RPC.
<LI CLASS="li-itemize">I/O operations on asynchronous queues can block, they should
therefore be done from a dedicated thread.
<LI CLASS="li-itemize">the AsyncEclipseQueue class does not extend InputStream or
OutputStream and can therefore not be used for I/O directly. Instead,
a standard Java InputStream can be obtained from it via the
getInputStream() method, and an OutputStream via the getOutputStream()
method.
<LI CLASS="li-itemize">on the ECLiPSe side, an event can (and should) be raised when
data arrives from the Java side. If the ECLiPSe side has control at
that time, it will handle the event. Otherwise, the event handling
may be deferred until ECLiPSe has control back.
</UL>
<A NAME="toc51"></A>
<H3 CLASS="subsection"><A NAME="htoc95">8.6.1</A>&nbsp;&nbsp;Opening and closing asynchronous queues</H3>
<A NAME="sec:ji-async-open-close"></A>
<A NAME="@default248"></A>
<A NAME="@default249"></A>
Opening and closing can be performed in a single step from
either the Java or the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> side.<BR>
<BR>

<H4 CLASS="subsubsection">Opening an asychronous queue using Java methods</H4>
The <I>AsyncEclipseQueue</I> does not have public
constructors. Instead, we invoke <TT>getAsyncEclipseQueue</TT>.
This asks the <I>EclipseConnection</I> object for a
reference to an <I>AsyncEclipseQueue</I> instance
which represents a new queue. To specify the stream for later
reference, we supply the method with a string which will equal to the
atom by which the queue is referred to as a stream in ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>. For
example the following code creates such a queue<A NAME="@default250"></A>:
<PRE CLASS="verbatim"> ...
  AsyncEclipseQueue java_eclipse_async = 
    eclipse.getAsyncEclipseQueue("java_eclipse_async");
...
</PRE>Note that this method will only work when the <TT>eclipse</TT> object is
an <I>OutOfProcessEclipse</I> or <I>RemoteEclipse</I>.
Teh method will create and return a new <I>AsyncEclipseQueue</I>
object, and will also open a stream with the
specified names on the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> side. No stream in ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> should
exist with the specified name. If a stream exists which has this name
and is not a queue between the Java object and ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>, the Java
method throws an exception. If the name is used by a pre-existing
queue, it is returned, so the <TT>getAsyncEclipseQueue</TT>
methods can also be used to retrieve the queue
objects by name once they have already been created.<BR>
<BR>
<A NAME="toc52"></A>
<H3 CLASS="subsection">Opening an asychronous queue using ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> predicates</H3>
<A NAME="@default251"></A>
You can use the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> builtin <A HREF="../bips/kernel/externals/peer_queue_create-5.html"><B>peer_queue_create/5</B></A><A NAME="@default252"></A> to open a
queue. Used correctly, these have the same effect as the Java methods
explained above. For the peer name, you should use the atom returned
by the <TT>getPeerName()</TT> method of the relevant <I>EclipseConnection</I> instance. The direction should be <TT>bidirect</TT>,
and the queue type should be specified as <TT>async</TT>.<BR>
<BR>

<H4 CLASS="subsubsection">Transferring data using Java methods</H4>
Once an <I>AsyncEclipseQueue</I> has been created, a standard Java
InputStream can be obtained from it via the getInputStream() method,
and an OutputStream via the getOutputStream() method.
These Java streams can be used as you would any instance of <I>java.io.InputStream</I> or <I>java.io.OutputStream</I>.
Unlike the synchronous <I>FromEclipseQueue</I> and <I>ToEclipseQueue</I>,
I/O on these streams can block, and should therefore be handled by dedicated
threads. For this reason, the listener-feature is not supported on
asynchronous queues.<BR>
<BR>

<H4 CLASS="subsubsection">Transferring data using ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> predicates</H4>
On the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> side, there are built-in predicates for writing to,
reading from and otherwise interacting with streams. Any of these may
be used. Perhaps most useful are <A HREF="../bips/kernel/ioterm/read_exdr-2.html"><B>read_exdr/2</B></A><A NAME="@default253"></A> and <A HREF="../bips/kernel/ioterm/write_exdr-2.html"><B>write_exdr/2</B></A><A NAME="@default254"></A>; these are explained in Section
<A HREF="embroot046.html#sec:ji-formatting-queue-data">8.5.2</A><A NAME="@default255"></A>. For the stream ID, you may either use the stream name, or the stream number, obtained for example using <A HREF="../bips/kernel/externals/peer_get_property-3.html"><B>peer_get_property/3</B></A><A NAME="@default256"></A>.<BR>
<BR>
Since the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> side does not support threads, it should only write to
an asynchronous queue when there is an active thread on the Java side to
read the data. Otherwise, the write-operation may block, and control will
never be transferred back from ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> to Java.<BR>
<BR>
For reading from an asynchronous queue, the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> side should
typically set up an event handler. The handler will be invoked whenever
new data arrives on a previously empty queue.
<PRE CLASS="verbatim">
my_async_queue_handler(Stream) :-
    ( select([Stream], 0, [_]) -&gt;
        read_exdr(Stream, Data),
        process(Data),
        my_async_queue_handler(Stream)
    ;
        events_nodefer
    ).

setup_async_queue_with_handler :-
    event_create(my_async_queue_handler(my_async_queue), [defers], Event),
    peer_queue_create(my_async_queue, host, async, bidirect, Event).
</PRE>Note that execution of the handler is only guaranteed when the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>
side has control.<BR>
<BR>
When communicating between Java and ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> using queues<A NAME="@default257"></A>, you
should always invoke the <TT>flush()</TT> method of the Java <I>OutputStream</I> which you have written to, whether it be a <I>ToEclipseQueue</I> or an <I>EXDROutputStream</I>. Similarly, on the
ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> side, <TT>flush/1</TT> should always be executed after
writing. Although in some cases reading of the data is possible
without a flush, flushing guarantees the transfer of data.
<BR>
<BR>

<H4 CLASS="subsubsection">Closing a queue using Java methods</H4>
This is done simply by calling the <TT>close()</TT><A NAME="@default258"></A> method on the <I>AsyncEclipseQueue</I> instance.<BR>
<BR>

<H4 CLASS="subsubsection">Closing a queue using ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> predicates</H4>
<A NAME="@default259"></A>
This is done by executing the builtin <A HREF="../bips/kernel/externals/peer_queue_close-1.html"><B>peer_queue_close/1</B></A><A NAME="@default260"></A>. Note
that the builtin <TT>close/1</TT> should not be used in this situation,
as it will not terminate the Java end of the queue.<BR>
<BR>
<A NAME="toc53"></A>
<H3 CLASS="subsection"><A NAME="htoc96">8.6.2</A>&nbsp;&nbsp;Writing and reading ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> terms on queues<A NAME="@default261"></A></H3>
See the corresponding section for synchronous queues, 
<A HREF="embroot046.html#sec:ji-formatting-queue-data">8.5.2</A>.<BR>
<BR>
<HR>
<A HREF="embroot046.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="embroot041.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
<A HREF="embroot048.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
